//
// Created by sgyt on 2020/3/19.
// 原子变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/sem.h>

static int sem_id;

union semun{
    int val;
    struct semid_ds *buf;
    unsigned short *arry;
};
//初始化信号量
static int set_semvalue();
//等待信号量
static int semaphore_p();
//发送信号量
static int semaphore_v();
//删除信号量
static void del_semvalue();

int main(int argc,char *argv[])
{
    int i = 0;
    char message = 'x';
    //创建信号量
    sem_id = semget((key_t)1234,1,0666|IPC_CREAT);

    if(argc > 1)
    {
        //初始化信号量
        if(!set_semvalue())
        {
            printf("init failed\n");
            exit(EXIT_FAILURE);
        }

        //参数的第一个字符赋给message;
        message = argv[1][0];
    }

    for(i = 0;i<5;i++)
    {
        //等待信号
        if(!semaphore_p())
        {
            exit(EXIT_FAILURE);
        }
        printf("%c",message);
        fflush(stdout);
        sleep(1);

        //发送信号量
        if(!semaphore_v())
        {
            exit(EXIT_FAILURE);
        }
        sleep(1);
    }

    printf("\n%d- finish\n",getpid());
    if(argc > 1)
    {
        //退出前删除信号量
        del_semvalue();
    }
    return EXIT_SUCCESS;
}

int set_semvalue()
{
    union  semun sem_unin;
    sem_unin.val = 1;
    if(semctl(sem_id,0,SETVAL,sem_unin) == -1)
    {
        return 0;
    }
    return 1;
}

int semaphore_p()
{
    struct sembuf sem_b;
    sem_b.sem_num = 0;
    sem_b.sem_op = -1;
    sem_b.sem_flg = SEM_UNDO;
    if(semop(sem_id,&sem_b,1)==-1)
    {
        printf("semaphore_p failed\n");
        return 0;
    }
    return 1;
}

int semaphore_v()
{
    struct sembuf sem_b;
    sem_b.sem_num = 0;
    sem_b.sem_op = 1;
    sem_b.sem_flg = SEM_UNDO;

    if(semop(sem_id,&sem_b,1) == -1)
    {
        perror("semop is error\n");
        return 0;
    }
    return 1;
}

void del_semvalue()
{
    union semun sem_union;
    if(semctl(sem_id,0,IPC_RMID,sem_union) == -1)
    {
        perror("semctl is error\n");
        exit(EXIT_FAILURE);
    }
}

